package org.fast.project.web.vo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import org.fast.project.common.exception.AbstractBusinessException;
import org.fast.project.web.advice.GlobalExceptionResolverAdvice;
import org.fast.project.web.advice.GlobalRequestInterceptor;
import org.fast.project.web.advice.RequestContextUtil;

import java.time.LocalDateTime;

/**
 * @program: spring-web-archetype-advice
 * @description: 通用 服务调用 请求响应类
 * @author: lilith·bristol
 * @date : 2020-04-22 00:34
 **/

@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CommonResponse<T> {

    /**
     * <h2>全局请求识别码</h2>
     * 用于在系统中追踪请求链路 记录请求日志
     * <p>
     * 此识别码在全部请求中应为唯一
     * 或者至少保证在某一较长时间段唯一
     */
    private String requestId;

    /**
     * <h2>返回消息</h2>
     * 非业务流程中的消息
     * 而是调用链路中其他组件可能设置的 通知链路上下层的消息
     * 如 {@link GlobalExceptionResolverAdvice} {@link GlobalRequestInterceptor}
     * 设置的请求错误消息
     * 业务流程中的消息 在#data中设置
     */
    private String message;

    /**
     * <h2>返回消息识别码</h2>
     * 返回消息的标识码
     * 可用于其他系统从外部资源库加载返回信息
     * 以便国际化
     */
    private String messageCode;

    /**
     * <h2>返回 此次调用是否成功</h2>
     * 如果为true -> 说明调用成功 则调用方处理 #data 的数据
     * 如果为false -> 说明调用失败 则调用方处理 #exception 的数据
     */
    private Boolean success;

    /**
     * <h2>用户身份码</h2>
     */
    private String userId;

    /**
     * <h2>返回数据体</h2>
     * <p>
     * 调用成功 设置此数据体
     */
    private T data;

    /**
     * <h2>返回异常</h2>
     * 调用失败 设置异常内容体
     */
    private T exception;

    /**
     * <h2>本次调用结束时间</h2>
     */
    private LocalDateTime endTime;

    /**
     * @param data 返回的处理数据
     *
     * @return CommonResponse
     *
     * @author lilith·bristol
     * @description 创建一个成功请求的返回响应体
     * @date 2:21 2020/4/19
     */
    public static <T> CommonResponse<T> createSuccessResponse(T data) {
        return CommonResponse.<T>builder()
                .requestId(RequestContextUtil.getRequestId())
                .message("Success")
                .messageCode("[Server].[Success]")
                .success(true)
                .data(data)
                .endTime(LocalDateTime.now())
                .build();
    }

    /**
     * @param exception 业务错误
     * @return fast.project.vo.CommonResponse
     * @author lilith·bristol
     * @description 创建一个失败求的返回响应体
     * 异常信息exception会在全局异常处理器中处理 不会返回到请求端
     * @date 2:23 2020/4/19
     */
    public static CommonResponse<AbstractBusinessException> createFailureResponse(AbstractBusinessException exception) {
        return CommonResponse.<AbstractBusinessException>builder()
                .requestId(RequestContextUtil.getRequestId())
                .success(false)
                .message(exception.getMessage())
                .messageCode(exception.getErrorCode())
//                .exception(exception)
                .endTime(LocalDateTime.now())
                .build();
    }

    public static <T> CommonResponse<T> createFailureResponse(T exception) {
        return CommonResponse.<T>builder()
                .requestId(RequestContextUtil.getRequestId())
                .success(false)
                .exception(exception)
                .endTime(LocalDateTime.now())
                .build();
    }

    /**
     * @param message,messageCode,exception 错误信息 错误码 异常消息
     * @return fast.project.vo.CommonResponse
     * @author lilith·bristol
     * @description 创建一个失败求的返回响应体 用于系统框架级异常处理 业务场景不使用此方法
     * 异常信息exception会在全局异常处理器中处理 不会返回到请求端
     * @date 2:23 2020/4/19
     */
    public static CommonResponse<String> createFailureResponse(String message, String messageCode) {
        return CommonResponse.<String>builder()
                .requestId(RequestContextUtil.getRequestId())
                .success(false)
                .message(message)
                .messageCode(messageCode)
                .endTime(LocalDateTime.now())
                .build();
    }
}

